#pragma once

#include "Thread.hpp"
#include "lockGuard.hpp"
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include <unistd.h>

static const int N = 5;

// V4版本：使用自己封装的线程&使用lockGuard&使用单例模式
template <class T>
class ThreadPool
{
public:
    ThreadPool(int num = N) : _num(num)
    {
        pthread_mutex_init(&_lock, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    //获取单例对象的函数
    static ThreadPool<T>*getInstance()
    {
        if(instance==nullptr)
        {
            lockGuard lg(&instance_lock);
            if(instance==nullptr)
            {
                instance=new ThreadPool<T>();
                instance->init();
                instance->start();
            }
        }

        return instance;
    }

    // 线程初始化
    void init()
    {
        for (int i = 0; i < _num; ++i)
        {
            _threads.push_back(Thread(i, runRountine, this));
        }
    }

    // 线程启动
    void start()
    {
        for (auto &t : _threads)
        {
            t.run();
        }
    }

    // 返回任务队列是否为空
    bool isEmpty()
    {
        return _tasks.empty();
    }

    // 在条件变量上等待
    void condWait()
    {
        pthread_cond_wait(&_cond, &_lock);
    }

    // 取任务
    T popTask()
    {
        T t = _tasks.front();
        _tasks.pop();
        return t;
    }

    // 唤醒线程
    void wakeTask()
    {
        pthread_cond_signal(&_cond);
    }

    //获取互斥锁
    pthread_mutex_t *getLock()
    {
        return &_lock;
    }

    // 线程启动函数
    static void runRountine(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);

        while (true)
        {

            // 如果任务队列为空，则在条件变量等待
            T t;
            {
                lockGuard lg(tp->getLock());

                while (tp->isEmpty())
                {
                    tp->condWait();
                }
                t = tp->popTask();
            }

            t(); // 执行任务
        }
    }
    // 放任务
    void pushTask(const T &in)
    {
        lockGuard lg(&_lock);

        _tasks.push(in);
        wakeTask(); // 当前肯定有任务，唤醒在条件变量等待的线程

    }

    ~ThreadPool()
    {
        for (auto &t : _threads)
        {
            t.join();
        }

        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }

private:
    std::vector<Thread> _threads; // 线程池
    int _num;

    std::queue<T> _tasks;  // 任务列表

    pthread_mutex_t _lock; // 互斥锁
    pthread_cond_t _cond;  // 条件变量

    static ThreadPool<T>*instance;
    static pthread_mutex_t instance_lock;
};
//单例对象
template<class T>
ThreadPool<T>* ThreadPool<T>::instance=nullptr;

template<class T>
pthread_mutex_t ThreadPool<T>::instance_lock =PTHREAD_MUTEX_INITIALIZER;